package sharemem

import (
	"log"
//	"time"
	"server_cluster/battle/battle_config"
	"server_cluster/common/tools"
)

type Battle_area struct {
    shmUser_index   int32                           //共享内存数组下标
    is_active   bool                                //是否主动入战
    fight_num   int8                                //总场次
    fight_index int8                                //战斗场次
    action_index int32                              //前端操作位置
    card_num    int8                                //角色手牌总数量(大招除外)
    draw_time   int32                               //角色抽卡主轴时间
    root_time   int32                               //主轴时间
    node_time   int32                               //分轴时间
	ex_time		int32								//大招轴时间
	cd_time		int32								//技能卡cd时间
    real_time   int32                               //真实时间轴
    end_time    int32                               //战斗结束时间
    rage_time   int32                               //怒气恢复主轴时间(全场统一处理)
    role        [BATTLE_ROLE]*Battle_unit           //所有上阵角色
    role_assist [BATTLE_ROLE_ASSIST]*Battle_unit    //所有支援角色
    monster     [BATTLE_MONSTER]*Battle_unit        //所有怪物
    event_map   map[int32]map[int32]map[int32]int8  //主轴时间戳:分轴时间戳:大招轴时间戳:事件数量 (0刻时间初始化执行)
	real_event_map map[int32]int8					//真实时间戳:事件数量

	captain_skill	*BattleCaptain					//队长技
	conditions		[][]int32						//胜利条件
	is_completed	bool							//战斗是否完成
}

func (b *Battle_area)GetRealEventMap() map[int32]int8 {
	if b.real_event_map == nil {
		b.real_event_map = make(map[int32]int8,100)
	}
	return b.real_event_map
}

func (b *Battle_area)SetRealEventMap(real_time int32) {
	b.GetRealEventMap()[real_time] = 1
}

func (b *Battle_area)DelRealEventMap(real_time int32) {
	delete(b.GetRealEventMap(),real_time)
}

func (b *Battle_area)GetRootEventMap() map[int32]map[int32]map[int32]int8 {
    if b.event_map == nil {
        b.event_map = make(map[int32]map[int32]map[int32]int8,100)
    }
    return b.event_map
}

func (b *Battle_area)GetNodeEventMap(root_time int32) map[int32]map[int32]int8 {
	tmp := b.GetRootEventMap()
    if tmp[root_time] == nil {
        tmp[root_time] = make(map[int32]map[int32]int8,100)
    }
    return tmp[root_time]
}

func (b *Battle_area)GetExEventMap(root_time int32,node_time int32) map[int32]int8 {
	tmp := b.GetNodeEventMap(root_time)
    if tmp[node_time] == nil {
        tmp[node_time] = make(map[int32]int8,100)
    }
    return tmp[node_time]
}

func (b *Battle_area)SetEventMap(root_time int32,node_time int32,ex_time int32) {
    tmp := b.GetExEventMap(root_time,node_time)
    tmp[ex_time] = 1
}

func (b *Battle_area)DelRootEventMap(root_time int32) {
    delete(b.GetRootEventMap(),root_time)
}

func (b *Battle_area)DelNodeEventMap(root_time int32,node_time int32) {
    delete(b.GetNodeEventMap(root_time),node_time)
}

func (b *Battle_area)DelExEventMap(root_time int32,node_time int32,ex_time int32) {
    delete(b.GetExEventMap(root_time,node_time),ex_time)
}
//是否全部阵亡
func (b *Battle_area)IsAllDead(Type int8) bool {
	var i int8
	switch Type {
		case UNIT_TYPE_MONSTER:
			for i=0;i<BATTLE_MONSTER;i++ {
				if !b.monster[i].Exist(){
					continue
				}
				if b.monster[i].Alive() {
					return false
				}
			}
		case UNIT_TYPE_ROLE:
			for i=0;i<BATTLE_ROLE;i++ {
				if !b.role[i].Exist() {
					continue
				}
				if b.role[i].Alive() {
					return false
				}
			}
	}
	log.Printf("Type %d is all dead.",Type)
	return true
}

//获取阵亡数量
func (b * Battle_area)GetDeadNum(Type int8) int8 {
	var i,num int8
	num = 0
	switch Type {
		case UNIT_TYPE_MONSTER:
			for i=0;i<BATTLE_MONSTER;i++ {
				if !b.monster[i].Exist() {
					continue
				}
				if !b.monster[i].Alive() {
					num++
				}
			}
		case UNIT_TYPE_ROLE:
			for i=0;i<BATTLE_ROLE;i++ {
				if !b.role[i].Exist() {
					continue
				}
				if !b.role[i].Alive() {
					num++
				}
			}
	}
	return num
}
//获取存活数量
func (b *Battle_area)GetAliveNum(Type int8) int8 {
	var i,num int8
	num = 0
	switch Type {
		case UNIT_TYPE_MONSTER:
			for i=0;i<BATTLE_MONSTER;i++ {
				if !b.monster[i].Exist() {
					continue
				}
				if b.monster[i].Alive() {
					num++
				}
			}
		case UNIT_TYPE_ROLE:
			for i=0;i<BATTLE_ROLE;i++ {
				if !b.role[i].Exist() {
					continue
				}
				if b.role[i].Alive(){
					num++
				}
			}
	}
	return num
}


//效果层按规则选取目标
func (b *Battle_area)GetEffectTarget(rule int8,trigger *Battle_unit,target *Battle_unit) []*Battle_unit {
	var tmp []*Battle_unit
	switch rule {
		case 0:
			if target.IsHealthy() {
				tmp = append(tmp,target)
			}
		case 1:
			if trigger.IsHealthy() {
				tmp = append(tmp,trigger)
			}
		case 2:
			var i int8
			switch trigger.Type {
				case UNIT_TYPE_MONSTER:
					for i=0;i<BATTLE_ROLE;i++ {
						if b.role[i].IsHealthy() {
							tmp = append(tmp,b.role[i])
							break
						}
					}
				default:
					for i=0;i<BATTLE_MONSTER;i++ {
						if b.monster[i].IsHealthy() {
							tmp = append(tmp,b.monster[i])
							break
						}
					}
			}
		case 3:
			var i int8
			switch trigger.Type {
				case UNIT_TYPE_MONSTER:
					for i=0;i<BATTLE_MONSTER;i++ {
						if b.monster[i].IsHealthy() {
							tmp = append(tmp,b.monster[i])
							break
						}
					}
				default:
					for i=0;i<BATTLE_ROLE;i++ {
						if b.role[i].IsHealthy() {
							tmp = append(tmp,b.role[i])
							break
						}
					}
			}
		case 4:
			var i int8
			switch trigger.Type {
				case UNIT_TYPE_MONSTER:
					for i=0;i<BATTLE_ROLE;i++ {
						if b.role[i].IsHealthy() {
							tmp = append(tmp,b.role[i])
						}
					}
				default:
					for i=0;i<BATTLE_MONSTER;i++ {
						if b.monster[i].IsHealthy() {
							tmp = append(tmp,b.monster[i])
						}
					}
			}
		case 5:
			var i int8
			switch trigger.Type {
				case UNIT_TYPE_MONSTER:
					for i=0;i<BATTLE_MONSTER;i++ {
						if b.monster[i].IsHealthy() {
							tmp = append(tmp,b.monster[i])
						}
					}
				default:
					for i=0;i<BATTLE_ROLE;i++ {
						if b.role[i].IsHealthy() {
							tmp = append(tmp,b.role[i])
						}
					}
			}
		case 6:
			//随机敌方
			var i int8
			tmp_rand := make([]int8,0)
			switch trigger.Type {
				case UNIT_TYPE_MONSTER:
					for i=0;i<BATTLE_ROLE;i++ {
						if b.role[i].IsHealthy() {
							tmp_rand = append(tmp_rand,i)
						}
					}
				default:
					for i=0;i<BATTLE_MONSTER;i++ {
						if b.monster[i].IsHealthy() {
							tmp_rand = append(tmp_rand,i)
						}
					}
			}
			if len(tmp_rand) == 0 {
				return tmp
			}
			tmp_index := tools.GetResultByRegion(0,len(tmp_rand))
			switch trigger.Type {
				case UNIT_TYPE_MONSTER:
					tmp = append(tmp,b.role[tmp_rand[tmp_index]])
				default:
					tmp = append(tmp,b.monster[tmp_rand[tmp_index]])
			}
		case 7:
			//随机友方
			var i int8
			tmp_rand := make([]int8,0)
			switch trigger.Type {
				case UNIT_TYPE_MONSTER:
					for i=0;i<BATTLE_MONSTER;i++ {
						if b.monster[i].IsHealthy() {
							tmp_rand = append(tmp_rand,i)
						}
					}
				default:
					for i=0;i<BATTLE_ROLE;i++ {
						if b.role[i].IsHealthy() {
							tmp_rand = append(tmp_rand,i)
						}
					}
			}
			if len(tmp_rand) == 0 {
				return tmp
			}
			switch trigger.Type {
				case UNIT_TYPE_MONSTER:
					tmp_index := tools.GetResultByRegion(0,len(tmp_rand))
					tmp = append(tmp,b.monster[tmp_rand[tmp_index]])
				default:
					tmp_index := tools.GetResultByRegion(0,len(tmp_rand))
					tmp = append(tmp,b.role[tmp_rand[tmp_index]])
			}
		case 8:
			//随机友方两名
			var i int8
			tmp_rand := make([]int8,0)
			switch trigger.Type {
				case UNIT_TYPE_MONSTER:
					for i=0;i<BATTLE_MONSTER;i++ {
						if b.monster[i].IsHealthy() {
							tmp_rand = append(tmp_rand,i)
						}
					}
				default:
					for i=0;i<BATTLE_ROLE;i++ {
						if b.role[i].IsHealthy() {
							tmp_rand = append(tmp_rand,i)
						}
					}
			}
			if len(tmp_rand) == 0 {
				return tmp
			}
			switch trigger.Type {
				case UNIT_TYPE_MONSTER:
					tmp_index := tools.GetResultByRegion(0,len(tmp_rand))
					tmp = append(tmp,b.monster[tmp_rand[tmp_index]])
					tmp_index = tools.GetResultByRegion(0,len(tmp_rand))
					tmp = append(tmp,b.monster[tmp_rand[tmp_index]])
				default:
					tmp_index := tools.GetResultByRegion(0,len(tmp_rand))
					tmp = append(tmp,b.role[tmp_rand[tmp_index]])
					tmp_index = tools.GetResultByRegion(0,len(tmp_rand))
					tmp = append(tmp,b.role[tmp_rand[tmp_index]])
			}
		case 9:
			//随机敌方两名不重复
			var i int32
			tmp_rand := make([]int32,0)
			switch trigger.Type {
				case UNIT_TYPE_MONSTER:
					for i=0;i<BATTLE_ROLE;i++ {
						if b.role[i].IsHealthy() {
							tmp_rand = append(tmp_rand,i)
						}
					}
				default:
					for i=0;i<BATTLE_MONSTER;i++ {
						if b.monster[i].IsHealthy() {
							tmp_rand = append(tmp_rand,i)
						}
					}
			}
			if len(tmp_rand) == 0 {
				return tmp
			}
			switch trigger.Type {
				case UNIT_TYPE_MONSTER:
					tmp_index := tools.GetResultByRegion(0,len(tmp_rand))
					tmp = append(tmp,b.role[tmp_rand[tmp_index]])
					tmp_rand = tools.Remove(tmp_rand,int(tmp_index))
					if len(tmp_rand) == 0 {
						return tmp
					}
					tmp_index = tools.GetResultByRegion(0,len(tmp_rand))
					tmp = append(tmp,b.role[tmp_rand[tmp_index]])

				default:
					tmp_index := tools.GetResultByRegion(0,len(tmp_rand))
					tmp = append(tmp,b.monster[tmp_rand[tmp_index]])
					tmp_rand = tools.Remove(tmp_rand,int(tmp_index))
					if len(tmp_rand) == 0 {
						return tmp
					}
					tmp_index = tools.GetResultByRegion(0,len(tmp_rand))
					tmp = append(tmp,b.monster[tmp_rand[tmp_index]])
			}
		case 10:
			//血量最低的友方
			var i int8
			hp_min := int32(0)
			hp := int32(0)
			tmp_index := int8(-1)
			switch trigger.Type {
				case UNIT_TYPE_MONSTER:
					for i=0;i<BATTLE_MONSTER;i++ {
						if !b.monster[i].IsHealthy() {
							continue
						}
						hp = b.monster[i].TakeAtVal(VAL,HP)
						if hp_min == 0 || hp < hp_min {
							tmp_index = i
							hp_min = hp
						}
					}
				default:
					for i=0;i<BATTLE_ROLE;i++ {
						if !b.role[i].IsHealthy() {
							continue
						}
						hp = b.role[i].TakeAtVal(VAL,HP)
						if hp_min == 0 || hp < hp_min {
							tmp_index = i
							hp_min = hp
						}
					}
			}
			if tmp_index < 0 {
				return tmp
			}
			switch trigger.Type {
				case UNIT_TYPE_MONSTER:
					tmp = append(tmp,b.monster[tmp_index])
				default:
					tmp = append(tmp,b.role[tmp_index])
			}
		case 11:
			//除卡牌目标外的随机一个卡牌目标的友方角色
			var i int8
			tmp_rand := make([]int8,0)
			switch target.Type {
				case UNIT_TYPE_MONSTER:
					for i=0;i<BATTLE_MONSTER;i++ {
						if b.monster[i].IsHealthy() && i != target.index{
							tmp_rand = append(tmp_rand,i)
						}
					}
				default:
					for i=0;i<BATTLE_ROLE;i++ {
						if b.role[i].IsHealthy() && i != target.index{
							tmp_rand = append(tmp_rand,i)
						}
					}
			}
			if len(tmp_rand) == 0 {
				return tmp
			}
			switch trigger.Type {
				case UNIT_TYPE_MONSTER:
					tmp_index := tools.GetResultByRegion(0,len(tmp_rand))
					tmp = append(tmp,b.monster[tmp_rand[tmp_index]])
				default:
					tmp_index := tools.GetResultByRegion(0,len(tmp_rand))
					tmp = append(tmp,b.role[tmp_rand[tmp_index]])
			}
		case 12:
			//除卡牌目标外的随机一个卡牌目标的敌方角色
			var i int8
			tmp_rand := make([]int8,0)
			switch target.Type {
				case UNIT_TYPE_MONSTER:
					for i=0;i<BATTLE_ROLE;i++ {
						if b.role[i].IsHealthy() && i != target.index{
							tmp_rand = append(tmp_rand,i)
						}
					}
				default:
					for i=0;i<BATTLE_MONSTER;i++ {
						if b.monster[i].IsHealthy() && i != target.index{
							tmp_rand = append(tmp_rand,i)
						}
					}
			}
			if len(tmp_rand) == 0 {
				return tmp
			}
			switch trigger.Type {
				case UNIT_TYPE_MONSTER:
					tmp_index := tools.GetResultByRegion(0,len(tmp_rand))
					tmp = append(tmp,b.role[tmp_rand[tmp_index]])
				default:
					tmp_index := tools.GetResultByRegion(0,len(tmp_rand))
					tmp = append(tmp,b.monster[tmp_rand[tmp_index]])
			}
		case 13:
			//血量最低的敌方
			var i int8
			hp_min := int32(0)
			hp := int32(0)
			tmp_index := int8(-1)
			switch trigger.Type {
				case UNIT_TYPE_MONSTER:
					for i=0;i<BATTLE_ROLE;i++ {
						if !b.role[i].IsHealthy() {
							continue
						}
						hp = b.role[i].TakeAtVal(VAL,HP)
						if hp_min == 0 || hp < hp_min {
							tmp_index = i
							hp_min = hp
						}
					}
				default:
					for i=0;i<BATTLE_MONSTER;i++ {
						if !b.monster[i].IsHealthy() {
							continue
						}
						hp = b.monster[i].TakeAtVal(VAL,HP)
						if hp_min == 0 || hp < hp_min {
							tmp_index = i
							hp_min = hp
						}
					}
			}
			if tmp_index < 0 {
				return tmp
			}
			switch trigger.Type {
				case UNIT_TYPE_MONSTER:
					tmp = append(tmp,b.role[tmp_index])
				default:
					tmp = append(tmp,b.monster[tmp_index])
			}
	}
	return tmp
}

//按规则选取目标
func (b *Battle_area)GetCardTarget(rule int8,unit_trigger *Battle_unit,unit_target *Battle_unit) *Battle_unit {
	if unit_trigger == nil || !unit_trigger.Alive() {
		log.Printf("trigger is nil or not alive.")
		return nil
	}

	switch rule {
		case 1:
			//敌方单体
			if unit_target != nil && unit_target.Alive() && unit_trigger.Type != unit_target.Type && unit_target.Type != UNIT_TYPE_ROLE_ASSIST {
				//直接使用
				return unit_target
			}
			//重新选择
			var i int8
			switch unit_trigger.Type {
				case UNIT_TYPE_MONSTER:
					for i=0;i<BATTLE_ROLE;i++ {
						if b.role[i].IsHealthy() {
							return b.role[i]
						}
					}
				default:
					for i=0;i<BATTLE_MONSTER;i++ {
						if b.monster[i].IsHealthy() {
							return b.monster[i]
						}
					}
			}
		case 2:
			//我方单体
			if unit_target != nil && unit_target.Alive() && unit_trigger.Type == unit_target.Type && unit_target.Type != UNIT_TYPE_ROLE_ASSIST{
				//直接使用
				return unit_target
			}
			//重新选择
			var i int8
			switch unit_trigger.Type {
				case UNIT_TYPE_MONSTER:
					for i=0;i<BATTLE_MONSTER;i++ {
						if b.monster[i].IsHealthy() {
							return b.monster[i]
						}
					}
				default:
					for i=0;i<BATTLE_ROLE;i++ {
						if b.role[i].IsHealthy() {
							return b.role[i]
						}
					}
			}
		case 3:
			 //自己
			return unit_trigger
	}
	return nil
}

func (b *Battle_area)GetUnit(utype int8,uindex int8) *Battle_unit {
	switch utype {
		case UNIT_TYPE_ROLE:
			if uindex < 0 || uindex >= BATTLE_ROLE {
				log.Printf("get unit nil index = %d",uindex)
				return nil
			}
			return b.role[uindex]
		case UNIT_TYPE_MONSTER:
			if uindex < 0 || uindex >= BATTLE_MONSTER {
				log.Printf("get unit nil index = %d",uindex)
				return nil
			}
			return b.monster[uindex]
		case UNIT_TYPE_ROLE_ASSIST:
			if uindex < 0 || uindex >= BATTLE_ROLE_ASSIST {
				log.Printf("get unit nil index = %d",uindex)
				return nil
			}
			return b.role_assist[uindex]
	}
	log.Printf("get unit nil type = %d",utype)
	return nil
}

func (b *Battle_area)CheckConditions(Type bool,cond [][]int32,trigger *Battle_unit,target *Battle_unit) bool {
	if Type {
		for _,v := range cond {
			if !b.CheckCondition(v,trigger,target) {
				return false
			}
		}
		return true
	}else {
		for _,v := range cond {
			if b.CheckCondition(v,trigger,target) {
				return true
			}
		}
		return false
	}
}

//true 条件通过 false 条件未通过
func (b *Battle_area)CheckCondition(c []int32,trigger *Battle_unit,target *Battle_unit) bool {
	length := len(c)
	if length <= 0 {
		return false
	}
	switch c[0] {
		case 100:
			return true
		case 1:
			if !b.is_completed {
				return false
			}
			log.Printf("role alive num = %d c = %d",b.GetAliveNum(UNIT_TYPE_ROLE),c[1])
			return b.GetAliveNum(UNIT_TYPE_ROLE) >= int8(c[1])
		case 2:
			if c[1] < 0 || c[1] >= BATTLE_MONSTER {
				return false
			}
			monster := b.monster[c[1]]
			if !monster.Exist() {
				return false
			}
			hp_max := monster.TakeAtVal(VAL_MAX,HP)
			hp := monster.TakeAtVal(VAL,HP)
			return hp*10000 < hp_max*c[2]
		case 3:
			//属性值
			if length < 5 {
				log.Printf("config BattleCondition Param type-3 error.")
				return false
			}
			var unit *Battle_unit
			if c[1] == 1{
				if trigger == nil {
					return false
				}
				unit = trigger
			} else {
				if target == nil {
					return false
				}
				unit = target
			}
			hp := unit.TakeAtVal(VAL,HP)
			hp_max := unit.TakeAtVal(VAL_MAX,HP)
			if c[2] <= 5 && hp_max == 0 {
				log.Printf("check condition hp_max val = 0.")
				return false
			}
			switch c[2] {
				case 1:
					return hp*10000/hp_max == c[4]
				case 2:
					return hp*10000/hp_max > c[4]
				case 3:
					return hp*10000/hp_max < c[4]
				case 4:
					return hp*10000/hp_max >= c[4]
				case 5:
					return hp*10000/hp_max <= c[4]
				case 6:
					return unit.TakeAtVal(VAL_MAX,c[3]) == c[4]
				case 7:
					return unit.TakeAtVal(VAL_MAX,c[3]) > c[4]
				case 8:
					return unit.TakeAtVal(VAL_MAX,c[3]) < c[4]
				case 9:
					return unit.TakeAtVal(VAL_MAX,c[3]) >= c[4]
				case 10:
					return unit.TakeAtVal(VAL_MAX,c[3]) <= c[4]
			}
		case 4:
			//buff 层数
			if length < 6 {
				log.Printf("config BattleCondition Param type-4 error.%d",length)
				return false
			}
			var buff *Buff_have
			sub_type := int8(c[2])
			if c[1] == 1 {
				buff = trigger.GetBuffMap(sub_type)[c[3]]
			} else {
				buff = target.GetBuffMap(sub_type)[c[3]]
			}
			if buff == nil {
				return false
			}
			level := int32(buff.level)
			switch c[4] {
				case 1:
					return level == c[5]
				case 2:
					return level > c[5]
				case 3:
					return level < c[5]
				case 4:
					return level >= c[5]
				case 5:
					return level <= c[5]
			}
		case 5:
			//buff
			if length < 3 {
				log.Printf("config BattleCondition Param type-5 error.")
				return false
			}
			var all map[int32]*Buff_have
			sub_type := int8(c[2])
			if c[1] == 1 {
				all = trigger.GetBuffMap(sub_type)
			} else {
				all = target.GetBuffMap(sub_type)
			}
			return len(all) > 0
		case 6:
			if length < 2 {
				log.Printf("config BattleCondition Param type-6 error.")
				return false
			}
			//概率
			return tools.GetResultByPro(c[1])
		default:
			return true
	}
	return false
}

//1未完成 2胜利结束 3失败结束 4完成
func (b *Battle_area)FightOver() int8 {
	if b.CheckConditions(true,b.conditions,nil,nil) {
		return 2
	}
	if b.root_time >= b.end_time || b.IsAllDead(UNIT_TYPE_ROLE){
		//时间到 或 已方全死
		return 3
	}
	//敌方全死
	if b.IsAllDead(UNIT_TYPE_MONSTER) {
		return 4
	}
	return 1
}

func (b *Battle_area)DoRageAddByTime() {
	//log.Printf("do rage add by time start...rage_time = %d root_time=%d",b.rage_time,b.root_time)
	if b.rage_time > b.root_time {
		return
	}
	var i int8
	log.Printf("开始统一恢复怒气")
	//moster
	for i=0;i<BATTLE_MONSTER;i++ {
		if !b.monster[i].Alive() {
			continue
		}
		b.monster[i].RageAddByTime()
	}
	//role_assist
	for i=0;i<BATTLE_ROLE_ASSIST;i++ {
		if !b.role_assist[i].Alive() {
			continue
		}
		b.role_assist[i].RageAddByTime()
	}
	//role
	for i=0;i<BATTLE_ROLE;i++ {
		if !b.role[i].Alive() {
			continue
		}
		b.role[i].RageAddByTime()
	}
	b.rage_time += battle_config.RAGE_TIME
	b.SetEventMap(b.rage_time,0,0)
	//log.Printf("下次恢复怒气时间 %d",b.rage_time)
}

func (b *Battle_area)GetRoleSpeedAvg() int32 {
	var i int8
	speed_total := int32(0)
	unit_num := int32(0)
	for i=0;i<BATTLE_ROLE;i++ {
		if !b.role[i].Alive() {
			continue
		}
		attr := b.role[i].TakeAtVal(VAL_MAX,SPEED)
		unit_num++
		speed_total += attr
	}
	if unit_num <= 0 {
		return 0
	}
	return speed_total/unit_num
}

func (b *Battle_area)DoDrawCard() {
	if b.draw_time > b.root_time {
		return
	}
	var i int8
	speed := b.GetRoleSpeedAvg()
	num := battle_config.CARD_NUM_MAX - b.card_num
	log.Printf("开始统一抽卡...num = %d,draw_time=%d root_time=%d",num,b.draw_time,b.root_time)
	if num > 0 {
		//role
		for i=0;i<BATTLE_ROLE;i++ {
			if !b.role[i].Alive() {
				continue
			}
			if num <= 0 {
				break
			}
			//开始抽卡
			b.role[i].DrawCard(1)
			//
			num--
			b.card_num++
			log.Printf("unit %d card = %v",i,b.role[i].GetDrawCardMap())
		}
	}

	b.draw_time += (battle_config.GET_CARD_REF_TIME - battle_config.GET_CARD_COEF * (speed - battle_config.SPEED_REF_VALUE))
	b.SetEventMap(b.draw_time,0,0)
	log.Printf("下一次抽卡时间 %d",b.draw_time)
	//被动触发
	b.DoPassive(2)
	//触发队长技
	if b.root_time == 0 {
		b.DoCaptainSkill(CAPTAIN_TYPE_DRAW_FIRST)
	} else {
		b.DoCaptainSkill(CAPTAIN_TYPE_DRAW)
	}
}

func (b *Battle_area)DoCaptainSkill(Type int8) {
	if b.captain_skill == nil {
		return
	}
	if b.captain_skill.Type != Type {
		return
	}
	log.Printf("队长技开始")
	switch b.captain_skill.Param[0] {
		case 1:
			num := battle_config.CARD_NUM_MAX - b.card_num
			if num == 0 {
				return
			}
			if !tools.GetResultByPro(b.captain_skill.Param[1]) {
				return
			}
			tmp_rand := make([]int8,0)
			var i int8
			for i=0;i<BATTLE_ROLE;i++ {
				if !b.role[i].Alive() || (b.captain_skill.Param[2] != 0 && b.role[i].tag != int8(b.captain_skill.Param[2])){
					continue
				}
				tmp_rand = append(tmp_rand,i)
			}
			for i=0;i<int8(b.captain_skill.Param[3]);i++ {
				if num == 0 {
					return
				}
				b.role[tmp_rand[tools.GetResultByRegion(0,len(tmp_rand))]].DrawCard(1)
				num--
				b.card_num++
			}
		default:
			log.Printf("captain skill param[0] not found.")
	}
	log.Printf("队长技结束")
}

func (b *Battle_area)DoOrder() {
	//log.Printf("do order start...")
	var i int8
	for i=0;i<BATTLE_ROLE;i++ {
		if !b.role[i].IsHealthy(){
			//已阵亡 或 被控制
			continue
		}
		if b.role[i].order_time > b.root_time {
			continue
		}
		//log.Printf("role order_time = %d root_time = %d",b.role[i].order_time,b.root_time)
		//使用序列
		if !b.role[i].UseOrder() {
			log.Printf("role-%d use order error.",i)
			continue
		}
		b.role[i].order_index++
		if b.role[i].order_index >= b.role[i].order_max {
			b.role[i].order_index = 0
		}
		b.role[i].order_time += b.role[i].order[b.role[i].order_index].time
		b.SetEventMap(b.role[i].order_time,0,0)
		log.Printf("role-%d 下次普攻时间 %d",i,b.role[i].order_time)
	}
	for i=0;i<BATTLE_MONSTER;i++ {
		if !b.monster[i].IsHealthy(){
			//已阵亡 或 被控制
			continue
		}
		//先使用大招
		if b.monster[i].ex_card != nil && !b.monster[i].UseExCard(nil) {
			//log.Printf("monster use ex card error.i=%d",i)
		}
		//log.Printf("monster order_time = %d root_time = %d",b.monster[i].order_time,b.root_time)
		if b.monster[i].order_time > b.root_time {
			continue
		}
		//使用序列
		if !b.monster[i].UseOrder() {
			log.Printf("monster use order error.i=%d",i)
			continue
		}
		b.monster[i].order_index++
		if b.monster[i].order_index >= b.monster[i].order_max {
			b.monster[i].order_index = 0
		}
		b.monster[i].order_time += b.monster[i].order[b.monster[i].order_index].time
		b.SetEventMap(b.monster[i].order_time,0,0)
		log.Printf("monster-%d 下次普攻时间 %d",i,b.monster[i].order_time)
	}
}

func (b *Battle_area)DoBuff() {
	//log.Printf("do buff start...")
	var i int8
	for i=0;i<BATTLE_ROLE;i++ {
		if !b.role[i].Alive() {
			continue
		}
		b.role[i].CheckBuff()
	}

	for i=0;i<BATTLE_ROLE_ASSIST;i++ {
		if !b.role_assist[i].Alive() {
			continue
		}
		b.role_assist[i].CheckBuff()
	}

	for i=0;i<BATTLE_MONSTER;i++ {
		if !b.monster[i].Alive() {
			continue
		}
		b.monster[i].CheckBuff()
	}
}

func (b *Battle_area)DoCard() bool {
	if b.action_index < 0 {
		return true
	}
	user:=Get_user_by_index(b.shmUser_index)
	if user == nil {
		log.Printf("user not found.")
		return false
	}
	action := user.Get_action(b.action_index)
	if action == nil {
		b.action_index = -1
		log.Printf("action not found.")
		return true
	}

	if action.root_time > b.root_time || (action.root_time == b.root_time && action.node_time > b.node_time) {
		log.Printf("root_time action:%v area:%v node_time action:%v area:%v",action.root_time,b.root_time,action.node_time,b.node_time)
		return true
	}
	//
	log.Printf("开始出卡...index %v",action)
	unit_trigger := b.GetUnit(action.trigger_type,action.trigger)
	unit_target := b.GetUnit(action.target_type,action.target)
	if unit_trigger == nil || unit_target == nil{
		log.Printf("trigger or target not found.")
		return false
	}
	if !unit_trigger.Alive() || !unit_target.Alive(){
		//已阵亡 或 被控制
		log.Printf("trigger or target is dead.")
		return true
	}
	if !unit_trigger.UseCard(unit_target,action.card,action.num) {
		log.Printf("trigger use card error.")
		return false
	}
	log.Printf("出卡结束...index %d",b.action_index)
	//next action
	b.action_index++
	new_action := user.Get_action(b.action_index)
	if new_action != nil {
		b.SetEventMap(new_action.root_time,new_action.node_time,0)
	}
	return b.DoCard()
}

//Type 0游戏开始被动 1周期性被动 2队伍统一抽卡时
func (b *Battle_area)DoPassive(Type int8) {
	var i int8
	for i=0;i<BATTLE_ROLE;i++ {
		if !b.role[i].Alive() {
			continue
		}
		b.role[i].DoPassive(Type)
	}
	for i=0;i<BATTLE_ROLE_ASSIST;i++ {
		if !b.role_assist[i].Alive(){
			continue
		}
		b.role_assist[i].DoPassive(Type)
	}
	for i=0;i<BATTLE_MONSTER;i++ {
		if !b.monster[i].Alive(){
			continue
		}
		b.monster[i].DoPassive(Type)
	}
}

func (b *Battle_area)DoPassivePool() {
	//log.Printf("do passive start...")
	var i int8
	for i=0;i<BATTLE_ROLE;i++ {
		if !b.role[i].Alive() {
			continue
		}
		b.role[i].CheckAllPassivePool()
	}
	for i=0;i<BATTLE_ROLE_ASSIST;i++ {
		if !b.role_assist[i].Alive(){
			continue
		}
		b.role_assist[i].CheckAllPassivePool()
	}
	for i=0;i<BATTLE_MONSTER;i++ {
		if !b.monster[i].Alive(){
			continue
		}
		b.monster[i].CheckAllPassivePool()
	}
}

func (b *Battle_area)DoTough() {
	//log.Printf("do tough start...")
	var i int8
	for i=0;i<BATTLE_MONSTER;i++ {
		if !b.monster[i].Alive() || b.monster[i].tough_time == 0 || b.monster[i].tough_time > b.root_time{
			continue
		}
		//
		b.monster[i].ChangeAttr(VAL,TOUGH,b.monster[i].TakeAtVal(VAL_MAX,TOUGH))
		//
	}
}

func (b *Battle_area)DoSkill() {
	//log.Printf("do skill start...")
	var i int8
	for i=0;i<BATTLE_ROLE;i++ {
		if !b.role[i].Alive() {
			continue
		}
		b.role[i].CheckSkill()
	}
	for i=0;i<BATTLE_ROLE_ASSIST;i++ {
		if !b.role_assist[i].Alive(){
			continue
		}
		b.role_assist[i].CheckSkill()
	}
	for i=0;i<BATTLE_MONSTER;i++ {
		if !b.monster[i].Alive(){
			continue
		}
		b.monster[i].CheckSkill()
	}
}

func (b *Battle_area)GetNewTime(Type int8) int32 {
	last := int32(-1)
	switch Type {
		case 1:
			//root
			event := b.GetRootEventMap()
			for k,_ := range event {
				if last == -1 || k < last {
					last = k
				}
			}
			//log.Printf("root %v",event)
		case 2:
			//node
			event := b.GetNodeEventMap(b.root_time)
			for k,_ := range event {
				if last == -1 || k < last{
					last = k
				}
			}
			//log.Printf("node %v",event)
		case 3:
			//ex
			event := b.GetExEventMap(b.root_time,b.node_time)
			for k,_ := range event {
				if last == -1 || k < last {
					last = k
				}
			}
			//log.Printf("ex %v",event)
		case 4:
			//real
			event := b.GetRealEventMap()
			for k,_ := range event {
				if last == -1 || k < last{
					last = k
				}
			}
			//log.Printf("real %v",event)
	}
	return last
}

//遍历恢复怒气(时间周期)
//1循环完成(未结束) 2胜利结束 3失败结束|作弊结束
//遍历规则：上阵角色(0-3)->支援角色(0-1)->怪物(0-3)
func (b *Battle_area)FightExLoop() int8 {
//	time.Sleep(1000*time.Millisecond)
	//结束判断
	over := b.FightOver()
	if over != 1 {
		return over
	}
	if b.node_time == 0 {
		//以下均为主轴时间
		//抽卡
		b.DoDrawCard()
		//遍历恢复怒气(时间周期)
		b.DoRageAddByTime()
		//怪物回韧
		b.DoTough()
		//遍历序列(怪物大招->序列攻击)
		b.DoOrder()
		//遍历buff
		b.DoBuff()
	}
	//周期被动生效
	b.DoPassive(1)
	//出卡(主轴+分轴时间)

	if !b.DoCard() {
		return 3
	}
	//遍历运行主动技能及其效果
	b.DoSkill()
	//遍历运行被动技能及其效果
	b.DoPassivePool()
	return 1
}

func (b *Battle_area)FightNodeLoop() int8 {
	var new_time,c_time,new_real,c_real int32
	b.ex_time = 0
	res := int8(1)
	for ;res==1; {
		res = b.FightExLoop()
		b.DelRealEventMap(b.real_time)
		b.DelExEventMap(b.root_time,b.node_time,b.ex_time)
		//
		new_time = b.GetNewTime(3)
		c_time = new_time - b.ex_time
		new_real = b.GetNewTime(4)
		c_real = new_real - b.real_time
	//	log.Printf("res = %d root_time = %d node_time = %d ex_time = %d real_time = %d",res,b.root_time,b.node_time,b.ex_time,b.real_time)

		if new_time == -1 {
			break
		}
		//
		//递增大招轴时间差
		if c_time > c_real && new_real > 0{
			c_time = c_real
		}
		b.ex_time += c_time
		b.real_time += c_time
	}
	log.Printf("res = %d root_time = %d node_time = %d ex_time =%d real_time = %d end",res,b.root_time,b.node_time,b.ex_time,b.real_time)
	return res
}

//1循环完成(未结束) 2胜利结束 3失败结束|作弊结束
//遍历规则：上阵角色(0-3)->支援角色(0-1)->怪物(0-3)
func (b *Battle_area)FightRootLoop() int8 {
	var new_time,c_time,new_real,c_real int32
	b.node_time = 0
	res := int8(1)
	for ;res==1; {
		res = b.FightNodeLoop()
		b.DelRealEventMap(b.real_time)
		b.DelNodeEventMap(b.root_time,b.node_time)

		new_time = b.GetNewTime(2)
		c_time = new_time - b.node_time
		new_real = b.GetNewTime(4)
		c_real = new_real - b.real_time

	//	log.Printf("res = %d root_time = %d node_time = %d cd_time = %d real_time = %d",res,b.root_time,b.node_time,b.cd_time,b.real_time)
		if new_time == -1 {
			break
		}
		//递增分轴时间差
		if c_time > c_real && new_real > 0{
			c_time = c_real
		}
		b.node_time += c_time
		b.real_time += c_time
		b.cd_time += c_time
	}

	log.Printf("res = %d root_time = %d node_time = %d cd_time = %d real_time = %d end",res,b.root_time,b.node_time,b.cd_time,b.real_time)
	return res
}

func (b *Battle_area)RunFight() int8 {
	var new_time,c_time,new_real,c_real int32
	res := int8(1)
	//
	for;res==1;{
		res = b.FightRootLoop()
		b.DelRealEventMap(b.real_time)
		b.DelRootEventMap(b.root_time)

		new_time = b.GetNewTime(1)
		c_time = new_time - b.root_time
		new_real = b.GetNewTime(4)
		c_real = new_real - b.real_time

	//	log.Printf("res = %d root_time = %d cd_time = %d real_time = %d",res,b.root_time,b.cd_time,b.real_time)
		if new_time == -1 {
			break
		}
		//递增主轴时间差
		if c_time > c_real && new_real > 0{
			c_time = c_real
		}
		b.root_time += c_time
		b.real_time += c_time
		b.cd_time += c_time
	}
	log.Printf("res = %d root_time = %d cd_time = %d read_time = %d end_time = %d end",res,b.root_time,b.cd_time,b.real_time,b.end_time)
	return res
}
